package exercise;

public class EX05_OOP4 {

	// VO 클래스, Service 클래스 작성법 익히기

	public static void main(String[] args) {
		// #01
		RetangleVO r = new RetangleVO(4, 40, "red");
		float area = RetangleService.getArea(r.width, r.height);
		float perimeter = RetangleService.getPerimeter(r.width, r.height);
		System.out.println(area);
		System.out.println(perimeter);

		// #02
		// FanVO fvo = new FanVO(new FanVO.FAST, true, 10, "yellow");
		FanVO fvo1 = new FanVO(FanVO.FAST, true, 10, "yellow");
		String fan1 = FanService.toString(fvo1);

		FanVO fvo2 = new FanVO(FanVO.MEDIUM, false, 5, "blue");
		String fan2 = FanService.toString(fvo2);

		System.out.println(fan1);
		System.out.println(fan2);

		// #03
		AccountVO avo = new AccountVO(1122, 20000, 4.5F, "2013-11-07 07:52:32");
		float monthlyInterestRate = AccountService
				.getMonthlyInterestRate(avo.interestRate);

		AccountService.withDraw(avo.balance, 2500);
		// call by value (값에 의한 전달) 메서드의 매개 변수 유형이 기본 자료형인 경우
		// 기본 자료형 값을 메서드의 매개변수로 전달하면 JVM은 전달된 변수의 값을 메서드의 지역변수에 새로 복사해줌
		// 만일 지역변수의 값을 변경하더라도 전달해준 변수에는 영향을 미치지는 않음

		AccountService.withDraw(avo, 2500);
		// call by reference (주소에 의한 전달) 메서드의 매개 변수 유형이 참조 자료형인 경우
		// 참조형 변수를 메서드의 매개변수로 전달하면 지역번수는 참조형 변수가 전달해 준 객체를 가리키게 됨
		// 참조형 변수에 저장된 값은 실제 값이 아니고 그 값을 가리키는 주소를 의미함
		// 따라서 메서드에서 참조된 객체에 변경을 가하면 그 변화는 호출된 코드에도 반영됨

		AccountService.withDraw(avo, 3000);
		String str = "잔액 : " + avo.balance + " / 월간 이자율 : "
				+ monthlyInterestRate + " / 통장 개설날짜 : " + avo.dateCreated;
		System.out.println(str);

		// #04
		StockVO svo = new StockVO("경영기술", 1_000_000, 750_000);
		float changePercent = StockService.getChangePercent(
				svo.previousClosingPrice, svo.currentPrice);
		System.out.println(changePercent + "%");

	}

} // class

// #01
class RetangleVO {
	float width;
	float height;
	String color;

	public RetangleVO() {
		width = 1.0F;
		height = 1.0F;
		color = "white";
	}

	public RetangleVO(float width, float height, String color) {
		this.width = width;
		this.height = height;
		this.color = color;
	}
}

class RetangleService {
	static float getArea(float width, float height) {
		return width * height;
	}

	static float getPerimeter(float width, float height) {
		return width * 2 + height * 2;
	}
}

// #02
class FanVO {
	// 속도를 나타내는 상수들은 객체 생성없이 바로 사용가능해야 함
	// static final 예약어 사용
	// JDK5 이상에서는 이것을 대체하기 위해 Enum이라는 새로운 클래스 자료형이 추가됨
	static final int SLOW = 1;
	static final int MEDIUM = 2;
	static final int FAST = 3;
	int speed;
	boolean on;
	float radius;
	String color;

	public FanVO() {
		speed = this.SLOW;
		on = false;
		radius = 5.0F;
		color = "blue";
	}

	public FanVO(int speed, boolean on, float radius, String color) {
		this.speed = speed;
		this.on = on;
		this.radius = radius;
		this.color = color;
	}
}

class FanService {
	// 메서드 다중정의overloading
	// 메서드 서명만 다르면 메서드 이름은 동일하게 작성가능
	static String toString(float radius, String color, int speed, boolean on) {
		String msg = "";
		if (on) {
			msg = "속도 : " + speed + " / 색상 : " + color + "/ 지름 : " + radius
					+ " / 작동중";
		} else {
			msg = "색상 : " + color + " / 지름 : " + radius + " / 꺼져있음";
		}
		return msg;
	}

	static String toString(FanVO fvo) {
		String msg = "";
		if (fvo.on) {
			msg = "속도 : " + fvo.speed + " / 색상 : " + fvo.color + " / 지름 : "
					+ fvo.radius + " / 작동중";
		} else {
			msg = "색상 : " + fvo.color + " / 지름 : " + fvo.radius + " / 꺼져있음";
		}
		return msg;
	}
}

// #03
class AccountVO {
	int aid;
	int balance;
	float interestRate;
	String dateCreated;

	public AccountVO() {
		aid = 0;
		balance = 0;
		interestRate = 0;
	}

	public AccountVO(int aid, int balance, float interestRate,
			String dateCreated) {
		this.aid = aid;
		this.balance = balance;
		this.interestRate = interestRate;
		this.dateCreated = dateCreated;
	}

}

class AccountService {
	static float getMonthlyInterestRate(float interestRate) {
		return interestRate / 12;
	}

	static int withDraw(int balance, int money) {
		balance -= money;
		System.out.println("인출 후 잔액: " + balance);
		return balance;
	}

	static int withDraw(AccountVO avo, int money) {
		avo.balance -= money;
		System.out.println("인출 후 잔액: " + avo.balance);
		return avo.balance;
	}

	static int deposit(AccountVO avo, int money) {
		return avo.balance += money;
	}

}

// #04
class StockVO {
	String sname;
	int previousClosingPrice;
	int currentPrice;

	public StockVO() {
	}

	public StockVO(String sname, int previousClosingPrice, int currentPrice) {
		this.sname = sname;
		this.previousClosingPrice = previousClosingPrice;
		this.currentPrice = currentPrice;
	}
}

class StockService {
	static float getChangePercent(int previousClosingPrice, int currentPrice) {
		return (((float) currentPrice / previousClosingPrice) - 1) * 100;
	}
}
